package com.wunu.smartlock1.bluetooth.command

import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import kotlin.experimental.and

/**
 * Created by peiwei on 2018/4/21.
 */

public class CheckBindCommand: IComand {
    override var header: Byte = 0xc1.toByte()
    override fun payload(): ByteArray {
        val byteArrayOutputStream = ByteArrayOutputStream()
        byteArrayOutputStream.write(0xaa)
        byteArrayOutputStream.write(0xaa)
        byteArrayOutputStream.write(0xc0)//报文类型
        byteArrayOutputStream.write(0x00)//数据长度
        var sum = 0
        for (byte in byteArrayOutputStream.toByteArray()) {
            sum += byte
        }
        sum = sum.and(0xff)
        byteArrayOutputStream.write(sum)

        return byteArrayOutputStream.toByteArray()
    }

    override fun decode(byteArray: ByteArray): Map<String, Any> {
        val byteArrayInputStream = ByteArrayInputStream(byteArray)
        //读取头
        byteArrayInputStream.skip(2) //跳过头0xaaaa
        val cmd = byteArrayInputStream.read()
        if (cmd.toByte() != header) {
            return mapOf()
        }
        //读取长度
        byteArrayInputStream.read()
        //读取mac地址
        var macBytes = ByteArray(6)
        byteArrayInputStream.read(macBytes,0,6)
        //读取状态
        val state = byteArrayInputStream.read()
        //开始转换
        val macStr = macBytes.map { bytesToHexString(byteArrayOf(it)) }.reversed().joinToString(":")
        val state_ = state.toByte() == 0x01.toByte()
        return mapOf("mac" to macStr, "state" to state_)
    }
}

/*
* 绑定锁
* */
public class BindLockCommand(val basecode: Int, val openid: Int): IComand {
    override var header: Byte = 0xc3.toByte()
    override fun payload(): ByteArray {
        System.out.println("-----BindLockCommand payload-------");
        val byteArrayOutputStream = ByteArrayOutputStream()
        byteArrayOutputStream.write(0xaa)//报头
        byteArrayOutputStream.write(0xaa)//报头
        byteArrayOutputStream.write(0xc2)//报文类型
        byteArrayOutputStream.write(0x08)//数据长度
        System.out.println("BindLockCommand -> basecode:"+basecode);
        System.out.println("BindLockCommand -> openid:"+openid);
        byteArrayOutputStream.write(intToBytes(basecode))
        byteArrayOutputStream.write(intToBytes(openid))
        var sum = 0
        for (byte in byteArrayOutputStream.toByteArray()) {
            sum += byte
        }
        sum = sum.and(0xff)
        byteArrayOutputStream.write(sum)
        return byteArrayOutputStream.toByteArray()
    }

    /*
    * 绑定锁 返回结果[success: bool]
    * */
    override fun decode(byteArray: ByteArray): Map<String, Any> {
        System.out.println("-----BindLockCommand decode-------");
        val byteArrayInputStream = ByteArrayInputStream(byteArray)
        //读取头
        byteArrayInputStream.skip(2) //跳过头0xaaaa
        val cmd = byteArrayInputStream.read()
        if (cmd.toByte() != header) {
            return mapOf()
        }
        //读取长度
        byteArrayInputStream.read()
        //读取绑定结果
        val state = byteArrayInputStream.read()
        val success = state.toByte() == 0x01.toByte()
        return mapOf("success" to success)
    }
}

public class UnbindLockCommand(val basecode: Int, val openid: Int): IComand {
    override var header: Byte = 0xc5.toByte()
    override fun payload(): ByteArray {
        val byteArrayOutputStream = ByteArrayOutputStream()
        byteArrayOutputStream.write(0xaa)//报头
        byteArrayOutputStream.write(0xaa)//报头
        byteArrayOutputStream.write(0xc4)//报文类型
        byteArrayOutputStream.write(0x08)//数据长度
        byteArrayOutputStream.write(intToBytes(basecode))
        byteArrayOutputStream.write(intToBytes(openid))
        var sum = 0
        for (byte in byteArrayOutputStream.toByteArray()) {
            sum += byte
        }
        sum = sum.and(0xff)
        byteArrayOutputStream.write(sum)
        return byteArrayOutputStream.toByteArray()
    }
    /*
     * 解绑锁 返回结果[success: bool]
     * */
    override fun decode(byteArray: ByteArray): Map<String, Any> {
        val byteArrayInputStream = ByteArrayInputStream(byteArray)
        //读取头
        byteArrayInputStream.skip(2) //跳过头0xaaaa
        val cmd = byteArrayInputStream.read()
        if (cmd.toByte() != header) {
            return mapOf()
        }
        //读取长度
        byteArrayInputStream.read()
        //读取绑定结果
        val state = byteArrayInputStream.read()
        val success = state.toByte() == 0x00.toByte()
        return mapOf("success" to success)
    }
}

/*
* 查询电量
* */
public class CheckPowerCommand: IComand {
    override var header: Byte = 0xa5.toByte()
    override fun payload(): ByteArray {
        val byteArrayOutputStream = ByteArrayOutputStream()
        byteArrayOutputStream.write(0xaa)//报头
        byteArrayOutputStream.write(0xaa)//报头
        byteArrayOutputStream.write(0xa4)//报文类型
        byteArrayOutputStream.write(0x00)//数据长度
        var sum = 0
        for (byte in byteArrayOutputStream.toByteArray()) {
            sum += byte
        }
        sum = sum.and(0xff)
        byteArrayOutputStream.write(sum)
        return byteArrayOutputStream.toByteArray()
    }
    /*
    * 返回[power:Int](0 -- 100)
    * */
    override fun decode(byteArray: ByteArray): Map<String, Any> {
        val byteArrayInputStream = ByteArrayInputStream(byteArray)
        //读取头
        byteArrayInputStream.skip(2) //跳过头0xaaaa
        val cmd = byteArrayInputStream.read()
        if (cmd.toByte() != header) {
            return mapOf()
        }
        //读取长度
        byteArrayInputStream.read()
        //读取绑定结果
        val power = byteArrayInputStream.read()
        return mapOf("power" to power)
    }
}

public class OpenLockStep1Command(val xxtea: IntArray): IComand {
    override var header: Byte = 0xb1.toByte()
    override fun payload(): ByteArray {
        System.out.println("-----OpenLockSetp1Command payload-------");
        val byteArrayOutputStream = ByteArrayOutputStream()
        byteArrayOutputStream.write(0xaa)//报头
        byteArrayOutputStream.write(0xaa)//报头
        byteArrayOutputStream.write(0xb0)//报文类型
        byteArrayOutputStream.write(0x08)//数据长度
        for (v in xxtea){
            byteArrayOutputStream.write(intToBytes(v))
        }
        var sum = 0
        for (byte in byteArrayOutputStream.toByteArray()) {
            sum += byte
        }
        sum = sum.and(0xff)
        byteArrayOutputStream.write(sum)
        return byteArrayOutputStream.toByteArray()
    }

    override fun decode(byteArray: ByteArray): Map<String, Any> {
        System.out.println("-----OpenLockSetp1Command decode-------");
        val byteArrayInputStream = ByteArrayInputStream(byteArray)
        //读取头
        byteArrayInputStream.skip(2) //跳过头0xaaaa
        val cmd = byteArrayInputStream.read()
        if (cmd.toByte() != header) {
            return mapOf()
        }
        //读取长度
        byteArrayInputStream.read()
        //读取绑定结果
        val isOk = byteArrayInputStream.read()
        val n = byteArrayInputStream.read()
        return mapOf("n" to n, "success" to isOk)
    }
}

public class OpenLockSetp2Command(val xxtea: IntArray): IComand {
    override var header: Byte = 0xb3.toByte()
    override fun payload(): ByteArray {
        System.out.println("-----OpenLockSetp2Command payload-------");
        val byteArrayOutputStream = ByteArrayOutputStream()
        byteArrayOutputStream.write(0xaa)//报头
        byteArrayOutputStream.write(0xaa)//报头
        byteArrayOutputStream.write(0xb2)//报文类型
        byteArrayOutputStream.write(0x08)//数据长度
        for (v in xxtea){
            byteArrayOutputStream.write(intToBytes(v))
        }
        var sum = 0
        for (byte in byteArrayOutputStream.toByteArray()) {
            sum += byte
        }
        sum = sum.and(0xff)
        byteArrayOutputStream.write(sum)
        return byteArrayOutputStream.toByteArray()
    }

    override fun decode(byteArray: ByteArray): Map<String, Any> {
        System.out.println("-----OpenLockSetp2Command decode-------");
        val byteArrayInputStream = ByteArrayInputStream(byteArray)
        //读取头
        byteArrayInputStream.skip(2) //跳过头0xaaaa
        val cmd = byteArrayInputStream.read()
        if (cmd.toByte() != header) {
            return mapOf()
        }
        //读取长度
        byteArrayInputStream.read()
        //读取绑定结果
        val success = byteArrayInputStream.read()
        System.out.println("success -- "+success);
        return mapOf("success" to success)
    }
}

public fun bytesToHexString(byteArray: ByteArray): String {
    var hs = ""
    var stmp = ""
    for (i in 0..byteArray.count()-1) {
        stmp = Integer.toHexString(byteArray[i].toInt().and(0xff))
        if (stmp.length < 2) {
            hs += '0'
        }
        hs += stmp.toUpperCase()
    }
    return hs.toString()
}

fun toByteArray(source: Short): ByteArray {
    source.toByte()
    var target = byteArrayOf(0,0)
    target[0] = source.and(0xff).toByte()
    //target[1] = kotl
    return target
}
public fun shortToBytes(short: Short): ByteArray {
    var byteArray = ByteArray(2)
    byteArray[0] = short.and(0xff).toByte()
    byteArray[1] = ((short.toInt() shr 8) and 0xff).toByte()
    return  byteArray
}

public fun intToBytes(intValue: Int): ByteArray {
    var byteArray = ByteArray(4)
    byteArray[0] = intValue.and(0xff).toByte()
    byteArray[1] = ((intValue shr 8) and 0xff).toByte()
    byteArray[2] = ((intValue shr 16) and 0xff).toByte()
    byteArray[3] = ((intValue shr 24) and 0xff).toByte()
    return  byteArray
}

public fun longToBytes(longValue: Long): ByteArray {
    var byteArray = ByteArray(8)
    for(i in 0..7) {
        val n = i * 8
        byteArray[i] = ((longValue shr n) and 0xff).toByte()
    }
    return byteArray
}